const ATTRS = 'ATTRS'
const TEXT = 'TEXT'
const REMOVE = 'REMOVE'
const REPLACE = 'REPLACE'
let Index = 0

function diff(oldTree, newTree) {
    // 所有节点的补丁
    let patches = {}
    let index = 0
    // 递归，比较后的结果放进补丁包中
    walk(oldTree, newTree, index, patches)
    return patches
}

// 某个节点比较属性
function diffAttr(oldAttrs, newAttrs) {
    let patch = {}
    for (let key in oldAttrs) {
        if (oldAttrs[key] !== newAttrs[key]) {
            patch[key] = newAttrs[key] // 有可能是undefined
        }
    }

    for (let key in newAttrs) {
       if (!oldAttrs.hasOwnProperty(key)) {
        patch[key] = newAttrs[key]
       } 
    }
    return patch
}

// 比较两个节点的所有的子节点的不同
function diffChildren(oldChildren, newChildren, index, patches) {
    // 比较老的第一个子节点和新的第一个子节点
    oldChildren.forEach((child, idx) => {
        // 索引不应该是index了
        walk(child, newChildren[idx], ++Index, patches)
    })
}

function isString(node) {
    return Object.prototype.toString.call(node) === '[object String]'
}


// 比较两个节点
function walk(oldNode, newNode, index, patches) {
    // 当前节点的所有补丁
    let currentPatch = []

    if (!newNode) {
        currentPatch.push({type: REMOVE, index})
    } else if (isString(oldNode) && isString(newNode)) {
        if (oldNode !== newNode) {
            currentPatch.push({type: TEXT, text: newNode})
        }
    } else if (oldNode.type === newNode.type) {
        let attrs = diffAttr(oldNode.props, newNode.props)
        if (Object.keys(attrs).length > 0) {
            currentPatch.push({type: ATTRS, attrs: attrs})
        }
        // console.log(attrs)

        // 如果当前这个节点有子节点
        diffChildren(oldNode.children, newNode.children, index, patches)
    } else {
        // 当前oldNode下有多少层节点，让Index的序号来实现
        let childIndex = 0
        Index = findIndex(oldNode, childIndex) + Index
        currentPatch.push({type: REPLACE, newNode: newNode})
    }
    if (currentPatch.length > 0) {
        patches[index] = currentPatch
        // console.log(patches)
    }
}

function findIndex(oldNode,index) {
    if (Array.isArray(oldNode.children)) {
        oldNode.children.forEach(oldChild => { // li
            index++
            findIndex(oldChild)
        })
    } else {
        index++
    }
    return index
    
}

export default diff 